define('apps/common/AtSuggestion', ['core/jQuery', 'core/Caret', 'core/List', 'apps/common/Suggestion', 'core/InputListener'], function(require) {
    
    var $ = require('core/jQuery'),
        Caret = require('core/Caret'),
        Suggestion = require('apps/common/Suggestion'),
        InputListener = require('core/InputListener'),
        idPrefix = 'atsuggestion',
        mix = K.mix,
        genID = 0,
        
        TPL = {
            'areaHighLighter' : '<div class="_j_areahightlighter" style="position:absolute;word-wrap:break-word;overflow-y:auto;overflow-x:hidden;background:#fff;" />',
            'listCnt' : '<div class="ui_list list_suggest" id="_j_atsuggestlist" style="display:none;z-index:610" />'
        },
        
        // suggest类型
        TYPE_USER = 0, TYPE_GROUP = 1;
    
    var AtSuggestion = K.extend( function(opts) {
        
        // Suggestion id
        var id = idPrefix+'_'+(genID++);
        this.id = id;
        
        // Suggestion URL
        this.URL = '/friend/ajax/friend_suggest.php';
        
        // 缓存suggestion数目
        this.cacheSize = 100;
        
        // 多长时间间隔内不再反复请求
        this.interval = 200;

        this.suggestData = {};
        
        this.suggestList = null;
        
        this.targetPosition = 0;
        
        this.limit = 0;
        
        this.atTip = {
            'atBegin' : '你要提到谁？',
            'noFriend' : '你还没互相关注的人可以<span class="at">@</span>',
            'normal' : '<span class="at">@</span>好友姓名，该好友就能收到通知'
        };
        
        this.trigger = null;
        
        this.area = null;
        
        this.source = 'web'; // 使用源（默认：web，其他：plug）
        
        mix(this, opts);
        
        this.trigger = $(this.trigger);
        
        this.area = $(this.area);
        
        this.init();
        
        this.bindEvents();
        
    }, Suggestion );
    
    mix(AtSuggestion.prototype, {

        'bindEvents' : function() {
            
            var area = this.area;
            
            this.listenAt(); // at监听
            
            // 监听keyup
            area.keyup($.proxy(this.keyupListener, this));
            
            // blur隐藏
            area.blur($.proxy(function() {
                if(this.suggestList && !this.suggestList.mouseon) {
                    this.hide();
                }
            }, this));
            
            // 监听keydown
            if ($.browser.opera) { // opera下keydown事件不能被阻止
                area.keypress($.proxy(this.keydownListener, this));   
            } else {
                area.keydown($.proxy(this.keydownListener, this));   
            }
            
            if(this.trigger.length) { // @按钮点击
                this.trigger.click($.proxy(function(ev) {
                    Caret.insertContent(area, '@');
                    area.trigger('input');
                    ev.preventDefault();
                },this));
            }
        },
        
        'listenAt' : function() {
            this.atListener = new InputListener({
                'area' : this.area,
                'listenLetter' : '@',
                'atMode' : true
            });
            
            this.atListener.on('hit', $.proxy(this.hitAt, this));
            this.atListener.on('unhit', $.proxy(this.unHitAt, this));
        },
        
        'hitAt' : function(args) {
            var data = args.data;
            this.atOffset = data.offset;
            this.targetPosition = data.position;
            this.caretStart = data.caretStart;
            this.getSuggestion({'key':data.follow}, $.proxy(this.showSuggest, this));
        },
        
        'unHitAt' : function() {
            this.hide();
        },
        
        /**
         * 高亮背景（暂不启用）
         */
        'createHightLighter' : function() {
            var areaCnt = this.area.parent(),
                position = this.area.position();

            this.highLighterArea = $(TPL.areaHighLighter).css({
                'display' : 'block',
                'border' : '1px solid #fff',
                'font-family' : this.area.css('font-family'),
                'font-size'   : this.area.css('font-size'),
                'line-height' : this.area.css('line-height'),
                'padding-left'  : this.area.css('padding-left'),
                'padding-top'   : this.area.css('padding-top'),
                'padding-right' : this.area.css('padding-right'),
                'padding-bottom': this.area.css('padding-bottom'),
                'left' : position.left,
                'top' : position.top,
                'width' : this.area.width(),
                'height' : this.area.height()
            }).appendTo(areaCnt);
        },
        
        /**
         * 更新选中区域（暂不启用）
         */
        'updateHighLighter' : function() {
            var html = this.currVal,
                atNamesIndex = [],
                atNamesMatch = {},
                atNamesCopy = this.atNames.slice();
            
            html = this.htmlEntify(html);
            
            // 更新当前at的好友数组，并且记录每个at的位置
            K.forEach(atNamesCopy, $.proxy(function(name, index) {
                var startIndex = atNamesMatch[name] || 0,
                    nameIndex = html.slice(startIndex).indexOf(name);
                if(nameIndex !== -1) {
                    atNamesMatch[name] = nameIndex + startIndex + name.length;
                    atNamesIndex.push(nameIndex + startIndex);
                } else {
                    this.atNames.splice(index, 1);
                }
            }, this));
            
            // 生成新的hightLighter html
            var increase = 0;
            K.forEach(atNamesIndex, $.proxy(function(index, i) {
                var realIndex = index+increase,
                    name = this.atNames[i];
                html = html.slice(0, realIndex) + '<b style="font-weight:normal; color:#0000ff">' + name + '</b>' + html.slice(realIndex + name.length);
                increase += 49;
            }, this));
            
            this.highLighterArea.html(html);
        },
        
        /**
         * 主要是将一些@下拉框使用的键盘事件的默认行为阻止掉
         */
        'keydownListener' : function(ev) { 
            var keyCode = ev.keyCode;
            if(this.atListener.hit) { // 用来在suggest list显示的情况下阻止默认上、下、enter键盘事件
                if(keyCode === 38 || keyCode === 40 || keyCode === 13 || keyCode === 27) {
                    ev.preventDefault();
                }
            }
        },
        
        'keyupListener' : function(ev) {
            var keyCode = ev.keyCode;
            if(this.atListener.hit && keyCode === 27) { // esc 退出处理
            	if(this.suggestList && this.suggestList.container.is(':visible')) {
            		ev.stopPropagation();
            	}
                this.hide();
            }
        },

        /**
         * 获得了有效的suggest data之后，将其显示出来
         */
        'showSuggest' : function(data) {
            
            // 如果suggestlist还不存在，则为其创建list并初始化list行为
            if(!this.suggestList) { 
                this.initList();
                this.suggestList.on('outputvalue', $.proxy(this.receiveValue, this));
            }
            
            // 生成suggest数据
            var suggestHTML = '', tip = '';
            if(data.total === 0) {
                tip = this.atTip.noFriend;
            } else if(data.list && data.list.length) {
                suggestHTML = '<ul class="ui_list_bd">' + K.map(data.list, function(user) {
                    var html = '';
                    if(user.type === TYPE_USER) {
                        var focusTag = '', remark = '', logo = '', atName = '', limit = 26, showlimit = limit,
                            viewName = (user.disp_name == 1) ? user.name : user.nick, showName;
                        
                        // at之后显示的名字
                        if(user.dup_name) {
                            if(user.disp_name == 1) {
                                atName = user.name+'('+user.nick+')';
                            } else {
                            	atName = user.nick;
                            }
                        } else {
                            atName = viewName;
                        }

                        // 重名显示头像信息
                        if(user.dup_name && user.logo) {
                            logo = '<span class="ui_avatar"><img src="'+user.logo+'" width="15" height="15" /></span>';
                        }
                                
                        // 设置双向关注图标和备注信息
                        //if(user.isfriend === 3) {
                            //focusTag = '<i class="spr_icons i_refollow_color r"></i>';
                        //}
                        
                        // 显示截断
                        showName = K.subByte(viewName, limit+3, '...');
                        showlimit = limit - K.byteLen(viewName);
                        
                        // 备注信息
                        if(user.remark && showlimit > 1) {
                            remark = '<span class="c9" title="'+user.remark+'">('+K.subByte(user.remark, showlimit+3, '...')+')</span>';
                        }

                        html = '<li class="_j_listitem" data-type="'+user.type+'" data-id="'+user.id+'" data-name="'+viewName+'" data-atname="'+atName+'" ><a href="#">'+focusTag+showName+logo+remark+'</a></li>';
                    } else {
                        html = '<li class="_j_listitem" data-type="'+user.type+'" data-id="'+user.id+'" data-name="'+user.name+'" data-atname="'+user.name+'"><a class="circle" href="#"><i class="spr_icons i_circle"></i>'+user.name+'<span class="c9">'+user.num+'</span></a></li>';
                    }
                    return html;
                }).join('') + '</ul>';
                tip = this.atTip.normal;
            }
            
            // 显示
            if(tip && this.atListener.hit) {
                this.suggestList.show(suggestHTML + '<div class="ui_list_tip">' + tip + '</div>');
                K.fire('giflog', {'key':'jsstat', 'params':{'type' : 'pic_at', 'source':this.source}, 'withUid':true});
            } else {
                this.hide();
            }
        },
        
        /**
         * 个性化定制suggest下拉框
         */
        'initList' : function(List) {
            var _this = this, List = require('core/List');
            this.suggestList = new List({
                'trigger' : this.area,
                
                'createContainer' : function() {
                    this.container = $(TPL.listCnt).appendTo('body');
                },
                
                'getValue' : function() {
                    return this.container.find('.'+this.itemHoverClass).data('atname');
                },
                
                'updateList' : function(data) {
                    this.container.html(data);
                    this.container.find(this.itemSelector).first().addClass(this.itemHoverClass);
                    this.container.find(this.itemSelector).last().addClass('last');
                    _this.setListPosition();
                }
            });
        },
        
        /**
         * 将suggest下拉框定位到@的位置
         */
        'setListPosition' : function() {
            this.suggestList.container.css(this.atOffset);
        },
        
        /**
         * 当特定suggest item被选择之后，当前area接收选择值
         */
        'receiveValue' : function(args) {
            var areaVal = this.area.val(),
                caretPosition = this.caretStart,
                beforeAtString = areaVal.slice(0, this.targetPosition),
                afterCaretString = areaVal.slice(caretPosition),
                beforeCaretString = beforeAtString + '@' + args.data + ' ',
                newCaretPosition = beforeCaretString.length;
                
            this.area.val(beforeCaretString + afterCaretString);
            //this.currVal = beforeCaretString + afterCaretString;
            //this.atNames.push(args.data);
            //this.updateHighLighter();
            this.suggestList.hide();
            Caret.setCaretPosition(this.area, newCaretPosition, newCaretPosition);
        },
        
        'hide' : function() {
            if(this.suggestList && this.suggestList.container.is(':visible')) {
                this.suggestList.hide();
            }
        }
    });
    
    return AtSuggestion;
});